#pragma once

namespace utility {
template <class T>
class AutoPtr {
public:
    AutoPtr() : _data(nullptr) {}

    AutoPtr(T* data) : _data(data) {}

    AutoPtr(AutoPtr& other) : _data(other.release()) {}

    ~AutoPtr() {
        if (_data != nullptr) {
            delete _data;
            _data = nullptr;
        }
    }

    T* get() const { return _data; }

    T* release() {
        auto data = _data;
        _data = nullptr;
        return data;
    }

    void reset(T* data = nullptr) {
        if (_data != data) {
            delete _data;
            _data = data;
        }
    }

    T* operator->() const { return _data; }

    T& operator*() const { return *_data; }

    AutoPtr& operator=(const AutoPtr<T>& other) {
        if (this == &other) {
            return *this;
        }
        reset(other.release());
        return *this;
    }

private:
    T* _data;
};
};  // namespace utility